﻿using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MediatR.Wrappers
{
    public abstract class RouteNotificationHandlerWrapper
    {
        public abstract Task Handle(IRouteNotification routeNotification, IServiceProvider serviceFactory,
            Func<IEnumerable<RouteNotificationHandlerExecutor>, IRouteNotification, CancellationToken, Task> publish,
            CancellationToken cancellationToken);
    }

    public class RouteNotificationHandlerWrapperImpl<TNotification> : RouteNotificationHandlerWrapper
    where TNotification : IRouteNotification
    {
        public override Task Handle(IRouteNotification routeNotification, IServiceProvider serviceFactory,
            Func<IEnumerable<RouteNotificationHandlerExecutor>, IRouteNotification, CancellationToken, Task> publish,
            CancellationToken cancellationToken)
        {
            var handlers = serviceFactory
                .GetServices<IRouteNotificationHandler<TNotification>>()
                .Where(x => x.Route == routeNotification.Route)
                .Select(static x => new RouteNotificationHandlerExecutor(x, (theNotification, theToken) => x.Handle((TNotification)theNotification, theToken)));

            return publish(handlers, routeNotification, cancellationToken);
        }
    }

}
